package com.marver.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HttpsUtil {
	private static Logger logger = LoggerFactory.getLogger(HttpsUtil.class);
	
    private static class DefaultTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    public static Map<String,String> contenttype= Collections.synchronizedMap(new HashMap<String,String>());

    public static String getHttpResult(String urlStr, String content,int connectTimeout,int readTimeout) {
        URL url = null;
        HttpURLConnection connection = null;
        try {
            //创建URL对象
            url = new URL(urlStr);

            //通过URL对象与服务端建立连接
            connection = (HttpURLConnection) url.openConnection();
            //设置输入输出，客户端请求到服务端需要发送数据流(输出流写出),服务端响应给客户端,客户端需要接受数据流(输入流读取)
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setConnectTimeout(connectTimeout*1000);
            connection.setReadTimeout(readTimeout*1000);
            connection.setRequestMethod("POST");
            // 如果是struts2的action接收请求必须设置此属性,否者接收不到数据流
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setUseCaches(false);
            connection.connect();

            //将数据以流的方式写出到服务端
            DataOutputStream out = new DataOutputStream(connection.getOutputStream());
            out.write(content.getBytes("UTF-8"));
            out.flush();
            out.close();
            //接收服务端响应的数据流
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            StringBuffer buffer = new StringBuffer();
            String line = "";
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            reader.close();
            return buffer.toString();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
        return null;
    }

    /**
     * 获取访问者IP
     *
     * 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
     *
     * 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)， 如果还不存在则调用Request .getRemoteAddr()。
     *
     * @return
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

    public static String getContentType(String exp){
        if (HttpsUtil.contenttype.containsKey(exp)){
            return HttpsUtil.contenttype.get(exp);
        }else{
            return "application/octet-stream";
        }
    }

    /**
     * 
     * @param uri
     * @return
     * @throws IOException HttpsURLConnection
     */
    public static String getHttpsURLConnection(String uri,String requestMethod,String content) throws IOException {
        SSLContext ctx = null;
        logger.info("Request url="+uri);
        logger.info("Request Data="+content);
        try {
            ctx = SSLContext.getInstance("TLS");
            ctx.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() }, new SecureRandom());
        } catch (KeyManagementException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        SSLSocketFactory ssf = ctx.getSocketFactory();
        
        URL url = new URL(uri);
        HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
        httpsConn.setSSLSocketFactory(ssf);
        httpsConn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        //设置输入输出，客户端请求到服务端需要发送数据流(输出流写出),服务端响应给客户端,客户端需要接受数据流(输入流读取)
        httpsConn.setDoOutput(true);
        httpsConn.setDoInput(true);
        httpsConn.setConnectTimeout(10*1000);
        httpsConn.setReadTimeout(30*1000);
        httpsConn.setRequestMethod(requestMethod.toUpperCase());
        // 如果是struts2的action接收请求必须设置此属性,否者接收不到数据流
        httpsConn.setRequestProperty("Content-Type", "application/json");
        httpsConn.setUseCaches(false);
        httpsConn.connect();
        
        //将数据以流的方式写出到服务端
        if(StringUtils.isNotEmpty(content)){
	        DataOutputStream out = new DataOutputStream(httpsConn.getOutputStream());
	        out.write(content.getBytes("UTF-8"));
	        out.flush();
	        out.close();
        }
        //接收服务端响应的数据流
        BufferedReader reader = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), "UTF-8"));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        while ((line = reader.readLine()) != null) {
                buffer.append(line);
        }
        reader.close();
        logger.info("Response Data="+buffer.toString());
        return buffer.toString();
        
        //return httpsConn;
    }

    //    public static void main(String [] arge){
//           /* String apiUrl="http://115.29.108.163:8755/api/userInfo/userRegister?accessToken=aa";
//            apiUrl=apiUrl+"&frPhone="+12;
//            User user =new User();
//            user.setLoginPwd("1234");
//            user.setPhone("1234");
//            user.setRegTerminal(1);
//            JSONObject content = JSONObject.fromObject(user);
//            System.out.println(content.toString());
//            String result= HttpsUtil.getHttpResult(apiUrl, content.toString());
//
//            System.out.println(result);*/
////            String apiUrl="http://115.29.108.163:8755/api/userInfo/login?accessToken=aa";
////            apiUrl +="&phone="+"13825792376"+"&loginPwd="+"23456"+"&userType="+0;
////            JSONObject sfObject = JSONObject.fromObject("ss");
//
//            String apiUrl="http://115.29.108.163:8755/api/userInfo/getUserInfo?accessToken=aa";
//            apiUrl +="&userId="+3;
//            String result= HttpsUtil.getHttpResult(apiUrl, "");
//            System.out.print(result);
//
//    }
}
